<template>
  <div class="chat-container">
    <!-- 主内容区域 -->
    <div class="main-content">
      <!-- 头部区域 -->
      <div class="header flex justify-between items-center p-4 bg-white border-b border-gray-200">
        <h2 class="text-2xl font-bold text-gray-800">智能408答疑</h2>
        <div class="status-icons">
          <span class="icon online">已联网</span>
          <span class="icon">长思考 (k1.5)</span>
        </div>
      </div>

      <!-- 聊天区域 -->
      <div class="chat-messages">
        <div v-for="(message, index) in messages" :key="index" class="message" :class="message.type">
          <!-- 新增模型标识显示 -->
          <div v-if="message.type === 'ai' && message.model" class="message-model">{{ message.model }} 回答</div>
          <!-- 使用 v-html 绑定 Markdown 渲染后的 HTML -->
          <div class="message-content" v-html="renderMarkdown(message.content)"></div>
        </div>
        <div v-if="isLoading" class="message ai">
          <!-- 显示思考中的状态 -->
          <div v-if="isThinking" class="thinking">思考中...</div>
          <!-- 流式响应也使用 v-html 绑定 Markdown 渲染后的 HTML -->
          <span v-if="streamResponse" v-html="renderMarkdown(streamResponse)"></span>
        </div>
      </div>

      <!-- 输入区域 -->
      <div class="input-area">
        <select v-model="selectedModel" class="model-select">
          <option value="qwen-plus">Qwen-Plus</option>
          <option value="doubao-thinking">doubao-thinking</option>
          <!-- <option value="doubao-thinking-vision">Doubao-Thinking-Vision</option> -->
          <option value="DeepSeek-R1">DeepSeek-R1</option>
          <option value="DeepSeek-V3">DeepSeek-V3</option>
           <option value="doubao-fine">微调大模型</option>
        </select>
        <input
          v-model="userInput"
          @keyup.enter="sendMessage"
          placeholder="输入你的问题..."
          :disabled="isLoading"
        />
        <button @click="sendMessage" :disabled="isLoading || !userInput.trim()">
          {{ isLoading ? '发送中...' : '发送' }}
        </button>
        <button @click="cancelRequest" :disabled="!isLoading">
          取消
        </button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { useTokenStore } from '@/stores/token';
import { marked } from 'marked';

marked.setOptions({
  sanitize: true,
});

const userInput = ref('');
const selectedModel = ref('DeepSeek-R1');
const messages = ref([]);
const isLoading = ref(false);
const streamResponse = ref('');
const isThinking = ref(false);
const controller = ref(null);
const dialogId = ref('');

const tokenStore = useTokenStore();

// 生成随机dialogId的函数
const generateRandomDialogId = () => {
  return 'dialog_' + Date.now() + '_' + Math.random().toString(36).substring(2, 10);
};

// 初始化dialogId，从本地存储读取或生成新的
const initDialogId = () => {
  const storedDialogId = localStorage.getItem('chatDialogId');
  if (storedDialogId) {
    dialogId.value = storedDialogId;
  } else {
    dialogId.value = generateRandomDialogId();
    localStorage.setItem('chatDialogId', dialogId.value);
  }
  console.log('使用的dialogId:', dialogId.value);
};

// 组件挂载时初始化dialogId
onMounted(() => {
  initDialogId();
});

function decodeMixedString(str) {
  return str
    .split('\n')
    .filter(line => line.trim().startsWith('data:'))
    .map(line => {
      try {
        const jsonStr = line.replace('data:', '').trim();
        if (!jsonStr) return '';
        
        const jsonData = JSON.parse(jsonStr);
        if (!jsonData.content) return '';
        
        return jsonData.content.replace(/\\u([0-9a-fA-F]{4})/g, (_, code) => 
          String.fromCodePoint(parseInt(code, 16))
        );
      } catch (e) {
        console.error('解析data行失败:', line, e);
        return '';
      }
    })
    .join('');
}

function renderMarkdown(text) {
  return marked(text || '');
}

const sendMessage = async () => {
  if (!userInput.value.trim() || isLoading.value) return;

  // 添加用户消息
  messages.value.push({
    type: 'user',
    content: userInput.value
  });

  const currentInput = userInput.value;
  userInput.value = '';
  isLoading.value = true;
  streamResponse.value = '';
  isThinking.value = false;

  try {
    controller.value = new AbortController();

    const token = tokenStore.token;

    const response = await fetch('http://localhost:8080/aichat/ask/stream', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${token}`
      },
      body: JSON.stringify({
        dialogId: dialogId.value, // 使用存储的dialogId
        ask: currentInput,
        mode: 0,
        model: selectedModel.value
      }),
      signal: controller.value.signal
    });

    if (!response.ok) {
      throw new Error('请求失败');
    }

    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      const chunk = decoder.decode(value, { stream: true });
      
      let check = true;
      try {
        decodeMixedString(chunk)
      } catch (e) {
        console.error('解析错误:', e);
        check = false;
      }
      if (check) {
        const content = decodeMixedString(chunk);
        console.log('接收到数据块和解码', chunk, content);
        if (content.startsWith('<think>')&&isThinking.value === false) {
          isThinking.value = true;
        } else if (content.endsWith('</think>')) {
          isThinking.value = false;
          streamResponse.value += content.slice(0, -8);
        } else {
          streamResponse.value += content;
        }
      }
    }
    console.log('流式响应结束:', streamResponse.value);
    
    // 流结束后添加模型信息到消息
    if (!controller.value || controller.value.signal.aborted === false) {
      const modelDisplayName = selectedModel.value === 'doubao-fine' ? '微调大模型' : selectedModel.value;
      messages.value.push({
        type: 'ai',
        content: streamResponse.value,
        model: modelDisplayName // 添加模型信息，如果是 doubao-thinking 则显示为“本地大模型”
      });
    }
  } catch (error) {
    if (error.name !== 'AbortError') {
      console.error('请求出错:', error);
      messages.value.push({
        type: 'ai',
        content: '抱歉，出错了: ' + error.message,
        model: selectedModel.value === 'doubao-fine' ? '微调大模型' : selectedModel.value // 错误时也显示模型
      });
    }
  } finally {
    isLoading.value = false;
    controller.value = null;
  }
};

const cancelRequest = () => {
  if (controller.value) {
    controller.value.abort();

    // 取消时如果有内容，添加模型信息
    if (streamResponse.value.trim() !== '') {
      messages.value.push({
        type: 'ai',
        content: streamResponse.value,
        model: selectedModel.value === 'doubao-fine' ? '微调大模型' : selectedModel.value
      });
    }

    isLoading.value = false;
    streamResponse.value = '';
    isThinking.value = false;

    messages.value.push({
      type: 'ai',
      content: '请求已取消',
      model: selectedModel.value === 'doubao-fine' ? '微调大模型' : selectedModel.value // 取消提示也显示模型
    });
  }
};
</script>

<style scoped lang="scss">
/* 样式保持不变 */
$primary-color: #4f46e5;        
$primary-light: #818cf8;       
$secondary-color: #f3f4f6;     
$text-color: #1f2937;          
$user-bubble-color: $primary-color; 
$ai-bubble-color: $secondary-color;  
$border-color: #e5e7eb;       
$shadow-color: rgba(0, 0, 0, 0.1); 

.chat-container {
  display: flex;
  height: 80vh;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  background-color: #f9fafb;
}

.main-content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex-grow: 1;
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
  background-color: transparent;
}

/* 新增模型标识样式 */
.message-model {
  font-size: 0.75rem;
  color: #6b7280;
  margin-bottom: 5px;
  font-weight: 500;
  display: block;
  border-bottom: 1px dashed #e5e7eb;
  padding-bottom: 3px;
}

/* 其他样式保持不变 */
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 0 15px 0;
  background-color: transparent;
  border-bottom: 1px solid $border-color;
}

.header h2 {
  font-size: 1.75rem;
  font-weight: 700;
  color: $text-color;
}

.status-icons {
  display: flex;
  gap: 12px;
  align-items: center;
}

.status-icons .icon {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 0.875rem;
  color: #6b7280;
}

.status-icons .online {
  color: #10b981;
}

.chat-messages {
  height: calc(100vh - 400px);
  overflow-y: auto;
  margin-bottom: 20px;
  padding: 10px;
  background-color: transparent;
  border-radius: 8px;
  scrollbar-width: thin;
  scrollbar-color: #cbd5e1 #f3f4f6;
}

.chat-messages::-webkit-scrollbar {
  width: 6px;
}

.chat-messages::-webkit-scrollbar-track {
  background: #f3f4f6;
}

.chat-messages::-webkit-scrollbar-thumb {
  background-color: #cbd5e1;
  border-radius: 10px;
}

.message {
  margin-bottom: 15px;
  padding: 12px 16px;
  border-radius: 18px;
  max-width: 80%;
  position: relative;
  animation: fadeIn 0.3s ease-in-out;
}

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.message.user {
  margin-left: auto;
  background-color: $user-bubble-color;
  color: white;
  border-bottom-right-radius: 4px;
  box-shadow: 0 4px 12px $shadow-color;
}

.message.user::before {
  content: '';
  position: absolute;
  bottom: 0;
  right: -10px;
  width: 20px;
  height: 20px;
  background-color: $user-bubble-color;
  clip-path: polygon(0 100%, 100% 100%, 100% 0);
}

.message.ai {
  margin-right: auto;
  background-color: $ai-bubble-color;
  color: $text-color;
  border-bottom-left-radius: 4px;
  box-shadow: 0 4px 12px $shadow-color;
}

.message.ai::before {
  content: '';
  position: absolute;
  bottom: 0;
  left: -10px;
  width: 20px;
  height: 20px;
  background-color: $ai-bubble-color;
  clip-path: polygon(100% 100%, 0 100%, 0 0);
}

.message-content {
  white-space: pre-wrap;
  word-wrap: break-word;
  line-height: 1.5;
  font-size: 0.975rem;
}

.thinking {
  background-color: #fef3c7;
  padding: 8px 12px;
  margin-bottom: 10px;
  border-radius: 8px;
  font-weight: 500;
  color: #92400e;
  display: inline-block;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.8; }
}

.input-area {
  display: flex;
  gap: 10px;
  margin-top: 20px;
  align-items: center;
}

.model-select {
  padding: 8px 12px;
  border: 1px solid $border-color;
  border-radius: 8px;
  background-color: white;
  color: $text-color;
  font-size: 0.9rem;
  min-width: 120px;
  box-shadow: 0 1px 3px $shadow-color;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px;
  cursor: pointer;
}

.input-area input {
  flex-grow: 1;
  padding: 12px 16px;
  border: 1px solid $border-color;
  border-radius: 24px;
  font-size: 0.975rem;
  transition: border-color 0.2s, box-shadow 0.2s;
  box-shadow: 0 1px 3px $shadow-color;
}

.input-area input:focus {
  outline: none;
  border-color: $primary-light;
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
}

.input-area button {
  padding: 10px 20px;
  background-color: $primary-color;
  color: white;
  border: none;
  border-radius: 24px;
  cursor: pointer;
  font-weight: 500;
  font-size: 0.9rem;
  transition: background-color 0.2s, transform 0.1s;
  box-shadow: 0 4px 6px $shadow-color;
}

.input-area button:hover:not(:disabled) {
  background-color: $primary-light;
  transform: translateY(-1px);
}

.input-area button:active:not(:disabled) {
  transform: translateY(0);
}

.input-area button:disabled {
  background-color: #e5e7eb;
  color: #9ca3af;
  cursor: not-allowed;
  box-shadow: none;
}

.typing-indicator {
  display: flex;
  gap: 3px;
  animation: blink 1.4s infinite;
  opacity: 0.6;
}

.typing-indicator span {
  width: 6px;
  height: 6px;
  background-color: $primary-color;
  border-radius: 50%;
  display: block;
  animation: typing 1.4s infinite ease-in-out;
}

.typing-indicator span:nth-child(1) { animation-delay: 0s; }
.typing-indicator span:nth-child(2) { animation-delay: 0.2s; }
.typing-indicator span:nth-child(3) { animation-delay: 0.4s; }

@keyframes typing {
  0%, 100% { transform: translateY(0); opacity: 0.6; }
  50% { transform: translateY(-5px); opacity: 1; }
}

@keyframes blink {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 0.1; }
}
</style>  